package cn.iocoder.yudao.module.system.service.file_storage.impl;

import cn.hutool.core.date.DateUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.module.system.controller.admin.a_pictures.vo.FileBaseVO;
import cn.iocoder.yudao.module.system.enums.StorageEnum;
import cn.iocoder.yudao.module.system.service.file_storage.FileStorageService;
import cn.iocoder.yudao.module.system.util.a_gaojian.DateTimeUtils;
import cn.iocoder.yudao.module.system.util.a_gaojian.FileUtil;
import jodd.net.URLDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.Date;
import java.util.List;

/**
 * @author zyk
 * 本地文件存储实现类
 */
@Slf4j
@Component
public class LocalStorageServiceImpl implements FileStorageService {

    @Value("${file.path}")
    private String filePath;

    @Override
    public FileBaseVO storage(MultipartFile file, String storage) {
        String fileName = URLDecoder.decode(file.getOriginalFilename(), "UTF-8");
        String ext = FileUtil.getExt(fileName);
        String datePath = DateUtil.format(new Date(), "yyyy/MM/dd");
        String localPath = storage + "/" + datePath;
        File localFile = new File(localPath);
        if (!localFile.exists()) {
            localFile.mkdirs();
        }
        String relaFile = datePath + "/" + DateTimeUtils.getFileName() + "." + ext;
        File realFile = new File(storage + "/" + relaFile);
        try {
            file.transferTo(realFile);
        } catch (IOException io) {
            log.error(io.getMessage());
            throw new ServiceException(new ErrorCode(500, "文件上传失败！"));
        }
        FileBaseVO fileBaseVO = new FileBaseVO();
        fileBaseVO.setFile(realFile);
        fileBaseVO.setRelativePath(relaFile);
        fileBaseVO.setAbsolutePath(realFile.getAbsolutePath());
        fileBaseVO.setExt(ext);
        fileBaseVO.setFileSize(file.getSize());
        return fileBaseVO;
    }

    @Override
    public FileBaseVO merge(List<File> list, Long size, String ext, String storagePath) {
        String datePath = DateUtil.format(new Date(), "yyyy/MM/dd");
        String localPath = storagePath + "/" + datePath;
        File localFile = new File(localPath);
        if (!localFile.exists()) {
            localFile.mkdirs();
        }
        String relaFile = datePath + "/" + DateTimeUtils.getFileName() + "." + ext;
        File realFile = new File(storagePath + "/" + relaFile);
        try (FileChannel outChannel = new FileOutputStream(realFile).getChannel()) {
            for (File file : list) {
                try (FileChannel inChannel = new FileInputStream(file).getChannel()) {
                    inChannel.transferTo(0, inChannel.size(), outChannel);
                } catch (IOException e) {
                    log.error("mergeFiles fail " + e.getMessage());
                }
            }
        } catch (IOException e) {
            log.error("mergeFiles fail " + e.getMessage());
        }
        if(size != cn.hutool.core.io.FileUtil.size(realFile)){
            log.error("文件大小不一致!");
            throw new ServiceException(501,"系统错误,请重新上传!");
        }
        for(File file : list){
            file.delete();
        }
        FileBaseVO fileBaseVO = new FileBaseVO();
        fileBaseVO.setFile(realFile);
        fileBaseVO.setRelativePath(relaFile);
        fileBaseVO.setAbsolutePath(realFile.getAbsolutePath());
        fileBaseVO.setExt(ext);
        fileBaseVO.setFileSize(size);
        return fileBaseVO;
    }

    @Override
    public boolean accept(String s) {
        return StorageEnum.local.getType().equals(s);
    }
}
